package own.rpc.nio;

import java.io.IOException;
import java.lang.reflect.Method;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import com.sun.jmx.defaults.ServiceName;

import own.nio.ChannelUtils;
import own.nio.CommHander;
import own.rpc.RPCServer;
import own.utils.Utils;

public class NioRPCServerImpl implements RPCServer {

	private static ExecutorService executor=Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
	
	private static Map<String,Class> registers=new HashMap<String, Class>();
	
	private static CommHander hander=new CommHander();
	
	
	@Override
	public void start() throws IOException {
		
		ServerSocketChannel server=ServerSocketChannel.open();
		server.socket().bind(new InetSocketAddress(9999));
		server.configureBlocking(false);
		Selector selector=Selector.open();
		server.register(selector, SelectionKey.OP_ACCEPT);
		
		while(selector.select()>0){
			Iterator<SelectionKey> keys=selector.selectedKeys().iterator();
			while(keys.hasNext()){
				SelectionKey key=keys.next();
				keys.remove();
				if(key.isValid()&&key.isAcceptable()){
					hander.handleAccept(key);
				}
				if(key.isReadable()){
					executor.submit(new ReadTask(key));
				}
				
			}
		}
	}

	@Override
	public void stop() {
//		executor.shutdown();
	}

	@Override
	public void register(Class serviceInterface, Class serviceImpl) {
		registers.put(serviceInterface.getName(), serviceImpl);
	}

	@Override
	public boolean isRuning() {
		// TODO Auto-generated method stub
		return false;
	}
	
	public static void execute(SelectionKey key){
		try {
			String msg=ChannelUtils.get(key);
			SocketChannel client = (SocketChannel) key.channel();
			JacksonJsonRedisSeriaziler jjrs=new JacksonJsonRedisSeriaziler();
			
			MessageBean mb=(MessageBean) jjrs.deserializeAsObject(msg, MessageBean.class);
			
			String serviceName=mb.getServiceName();
			String methodName=mb.getMethodName();
			System.out.println("serviceName:"+serviceName);
			System.out.println("methodName:"+mb.getMethodName());
			Class[] clazz=mb.getParamsTypes();
			Object[] objs=mb.getParams();
			Class service=registers.get(serviceName);
			Object object=null;
			try {
				Method method = service.getMethod(methodName, clazz);
				object =method.invoke(service.newInstance(), objs);
			} catch (Exception e) {
				e.printStackTrace();
			}
			ByteBuffer bb=ByteBuffer.wrap(jjrs.seriazileAsString(object).getBytes());
			client.write(bb);
		
		} catch (IOException e) {
			e.printStackTrace();
		}
	
		
		
	}
	
	static class ReadTask implements Runnable{
		SelectionKey key =null;
		public ReadTask(SelectionKey key){
			this.key=key;
		}

		@Override
		public void run() {
			execute(key);
		}
		
	}

}
